//#pragma once
//
//namespace primal
//{
//	namespace gfx
//	{
//		/*constexpr u32 FRAME_COUNT{};
//		using T = int;
//		constexpr bool BUILD_VIEW{};*/
//
//		template<typename T, u64 FRAME_COUNT, bool BUILD_VIEW>
//		class FrameResource : ComPtr<ID3D12Resource>
//		{
//		public:
//			FrameResource(Graphics* g);
//			~FrameResource();
//			void CopyData(u64 index, const T& data);
//			T& Element(u64 index);
//			descriptor_handle& get_handle(u64 index);
//			D3D12_GPU_VIRTUAL_ADDRESS get_address(u64 index);
//		private:
//			u64 m_element_size;
//			struct
//			{
//				T* buffer;
//				D3D12_GPU_VIRTUAL_ADDRESS address;
//				descriptor_handle view_handle;
//			}view[FRAME_COUNT];
//			Graphics* graphics;
//		};
//
//		template<typename T, u64 FRAME_COUNT, bool BUILD_VIEW>
//		FrameResource<T, FRAME_COUNT, BUILD_VIEW>::~FrameResource()
//		{
//			if (BUILD_VIEW)
//			{
//				for (auto& item : view)
//				{
//					graphics->srv->free(item.view_handle);
//				}
//			}
//			ptr_->Unmap(0u, nullptr);
//		}
//
//		template<typename T, u64 FRAME_COUNT, bool BUILD_VIEW>
//		inline void FrameResource<T, FRAME_COUNT, BUILD_VIEW>::CopyData(u64 index, const T & data)
//		{
//			memcpy(view[index].buffer, &data, sizeof(T));
//		}
//
//		template<typename T, u64 FRAME_COUNT, bool BUILD_VIEW>
//		inline T& FrameResource<T, FRAME_COUNT, BUILD_VIEW>::Element(u64 index)
//		{
//			return *view[index].buffer;
//		}
//
//		template<typename T, u64 FRAME_COUNT, bool BUILD_VIEW>
//		inline FrameResource<T, FRAME_COUNT, BUILD_VIEW>::FrameResource(Graphics* g) :ComPtr<ID3D12Resource>{}, m_element_size{ DXCONSTANTALIGN(sizeof(T)) }, graphics{ g }
//		{
//			d3dx::resource_desc desc{};
//			/*g->GetDevice()->CreateCommittedResource
//			(
//				&d3dx::heap_properties.upload_heap,
//				D3D12_HEAP_FLAG_NONE,
//				desc.as_buffer(m_element_size * FRAME_COUNT),
//				D3D12_RESOURCE_STATE_GENERIC_READ,
//				nullptr,
//				IID_PPV_ARGS(this->GetAddressOf())
//			);*/
//
//			auto address{ ptr_->GetGPUVirtualAddress() };
//			void* buffer_ptr{};
//			ptr_->Map(0u, nullptr, &buffer_ptr);
//			u64 buffer_ptr_u64{ reinterpret_cast<u64>(buffer_ptr) };
//
//			for (u64 i{}; i < FRAME_COUNT; ++i)
//			{
//				auto& buf{ this->view[i] };
//				auto offset{ i * m_element_size };
//				buf.address = address + offset;
//				buf.buffer = reinterpret_cast<T*>(buffer_ptr_u64 + offset);
//				if (BUILD_VIEW)
//				{
//					//g->srv->allocator(buf.view_handle);
//					d3dx::view_desc vd{};
//					//g->GetDevice()->CreateConstantBufferView(vd.as_constant(buf.address, m_element_size), buf.view_handle.cpu);
//				}
//			}
//		}
//
//		template<typename T, u64 FRAME_COUNT, bool BUILD_VIEW>
//		inline descriptor_handle& FrameResource<T, FRAME_COUNT, BUILD_VIEW>::get_handle(u64 index)
//		{
//			return view[index].view_handle;
//		}
//
//		template<typename T, u64 FRAME_COUNT, bool BUILD_VIEW>
//		inline D3D12_GPU_VIRTUAL_ADDRESS FrameResource<T, FRAME_COUNT, BUILD_VIEW>::get_address(u64 index)
//		{
//			return view[index].address;
//		}
//
//		template<typename T>
//		using ConstantBuffer = FrameResource<T, COMMAND_FRAME_COUNT, false>;
//	}
//}
//
///*
//
//template<typename T, u32 FRAME_COUNT>
//		class FrameResource : public ComPtr<ID3D12Resource>
//		{
//		public:
//			FrameResource(Graphics* g);
//
//			void CopyData(u32 index, const T& data);
//			void SetData(u32 index, const T& data);
//
//			descriptor_handle &handle(u32 index);
//			D3D12_GPU_VIRTUAL_ADDRESS get_address(u32 index);
//		private:
//			descriptor_handle handles[FRAME_COUNT];
//			D3D12_GPU_VIRTUAL_ADDRESS address[FRAME_COUNT];
//			u32 m_element_size;
//			u8* buffer;
//		};
//
//		template<typename T, u32 FRAME_COUNT>
//		inline FrameResource<T, FRAME_COUNT>::FrameResource(Graphics* g)
//		{
//			d3dx::resource_desc desc;
//			g->GetDevice()->CreateCommittedResource
//			(
//				&d3dx::heap_properties.upload_heap,
//				D3D12_HEAP_FLAG_NONE,
//				desc.as_buffer(m_element_size * FRAME_COUNT),
//				D3D12_RESOURCE_STATE_GENERIC_READ,
//				nullptr,
//				IID_PPV_ARGS(this->GetAddressOf())
//			);
//
//			auto address{ ptr_->GetGPUVirtualAddress() };
//			for (u32 i{}; i < FRAME_COUNT; ++i)
//			{
//				auto& item{ this->handles[i] };
//				auto& temp_address{ this->address[i] };
//				g->srv->allocator(item);
//				d3dx::view_desc vd{};
//				temp_address = address + static_cast<u64>((i * m_element_size));
//				auto desc_ptr{ vd.as_constant(temp_address, m_element_size) };
//				g->GetDevice()->CreateConstantBufferView(desc_ptr, item.cpu);
//			}
//
//			ptr_->Map(0u, nullptr, (void**)&buffer);
//		}
//
//		template<typename T, u32 FRAME_COUNT>
//		inline void FrameResource<T, FRAME_COUNT>::CopyData(u32 index, const T& data)
//		{
//			memcpy(&buffer[m_element_size * index], &data, sizeof(T));
//		}
//
//		template<typename T, u32 FRAME_COUNT>
//		inline void FrameResource<T, FRAME_COUNT>::SetData(u32 index, const T& data)
//		{
//			auto& buf{*((T*)&buffer[m_element_size * index])};
//			buf = data;
//		}
//
//		template<typename T, u32 FRAME_COUNT>
//		inline descriptor_handle& FrameResource<T, FRAME_COUNT>::handle(u32 index)
//		{
//			return handles[index];
//		}
//
//		template<typename T, u32 FRAME_COUNT>
//		inline D3D12_GPU_VIRTUAL_ADDRESS FrameResource<T, FRAME_COUNT>::get_address(u32 index)
//		{
//			return address[index];
//		}
//
//*/